package com.de.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ObjectUtils;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

@Slf4j
public class DateTimeUtils {
    public static final String DATE = "yyyy-MM-dd";
    public static final String DATE_TIME = "yyyy-MM-dd HH:mm:ss";

    /**
     * 获得当前时间yyyy-MM-dd
     *
     * @return Date
     */
    public static Date getCurrentDate() {
        return getCurrentDateTime("yyyy-MM-dd");
    }

    /**
     * 获得当前时间yyyy-MM-dd HH:mm:ss
     *
     * @return Date
     */
    public static Date getCurrentDateTime() {
        return getCurrentDateTime("yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 获得当前时间,指定格式
     *
     * @return Date
     */
    public static Date getCurrentDateTime(@NotNull String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date now = new Date();
        String tmp = sdf.format(now);
        try {
            return sdf.parse(tmp);
        } catch (ParseException e) {
            log.error("date transfer error ", e);
            return null;
        }
    }

    /**
     * 获得昨天yyyy-MM-dd格式的字符串
     *
     * @return YYYY-MM-DD格式的
     */
    public static String getYesterday() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = new GregorianCalendar();
        calendar.add(Calendar.DATE, -1);
        return format.format(calendar.getTime());
    }

    /**
     * 获得当前日期yyyy-MM-dd格式的字符串
     *
     * @return YYYY-MM-DD格式的
     */
    public static String getCurrentDateString() {
        return getCurrentDateTimeString("yyyy-MM-dd");
    }

    /**
     * 获得当前日期和时间,日期加时分秒,yyyy-MM-dd hh:mm:ss
     *
     * @return yyyy-MM-dd hh:mm:ss格式
     */
    public static String getCurrentDateTimeString() {
        return getCurrentDateTimeString("yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 获得当前日期和时间,指定格式
     *
     * @return 指定格式日期字符串
     */
    public static String getCurrentDateTimeString(@NotBlank String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date now = new Date();
        return sdf.format(now);
    }

    /**
     * 将时间字符串转换为'yyyy-MM-dd HH:mm:ss'的Date
     *
     * @param param yyyy-MM-dd HH:mm:ss格式日期字符串
     * @return Date
     */
    public static Date parse(@NotBlank String param) {
        return parse(param, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 将时间字符串转换为'yyyy-MM-dd'的Date
     *
     * @param param yyyy-MM-dd格式日期字符串
     * @return Date
     */
    public static Date parseShort(@NotBlank String param) {
        return parse(param, "yyyy-MM-dd");
    }

    /**
     * 将时间字符串转换为指定格式的的Date
     *
     * @param param  时间字符串
     * @param format 时间格式：如：yyyy/MM/dd
     * @return Date
     */
    public static Date parse(@NotBlank String param, @NotBlank String format) {
        Date date = null;
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        try {
            date = sdf.parse(param);
        } catch (ParseException ex) {
            // exception
            log.error("date to tate string failed ", ex);
        }
        return date;
    }

    /**
     * 将Date时间转换yyyy-MM-dd HH:mm:ss格式的时间字符串
     *
     * @param date 日期date
     * @return yyyy-MM-dd HH:mm:ss格式日期字符串
     */
    public static String formatDateTime(@NotNull Date date) {
        return format(date, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 将Date时间转换yyyy-MM-dd格式的时间字符串
     *
     * @param date 日期date
     * @return yyyy-MM-dd格式日期字符串
     */
    public static String formatDate(@NotNull Date date) {
        return format(date, "yyyy-MM-dd");
    }

    /**
     * 将Date转换为指定格式的时间字符串
     *
     * @param date   时间date
     * @param format 时间格式：如：yyyy/MM/dd
     * @return 指定format格式的日期字符串
     */
    public static String format(@NotNull Date date, @NotBlank String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }

    /**
     * 将Date转换成指定的小时分钟HH:mm
     *
     * @param date 日期date
     * @return HH:mm
     */
    public static String time2String(@NotNull Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        return sdf.format(date);
    }

    /**
     * 返回一定时间后的日期
     *
     * @param date  开始计时的时间
     * @param year  增加的年
     * @param month 增加的月
     * @param day   增加的日
     * @return Date
     */
    public static Date getAfterDate(Date date, int year, int month, int day) {
        return getAfterDate(date, year, month, day, 0, 0, 0);
    }

    /**
     * 返回一定时间后的日期
     *
     * @param date   开始计时的时间
     * @param year   增加的年
     * @param month  增加的月
     * @param day    增加的日
     * @param hour   增加的小时
     * @param minute 增加的分钟
     * @param second 增加的秒
     * @return Date
     */
    public static Date getAfterDate(Date date, int year, int month, int day, int hour, int minute, int second) {
        if (date == null) {
            date = new Date();
        }
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        if (year != 0) {
            cal.add(Calendar.YEAR, year);
        }
        if (month != 0) {
            cal.add(Calendar.MONTH, month);
        }
        if (day != 0) {
            cal.add(Calendar.DATE, day);
        }
        if (hour != 0) {
            cal.add(Calendar.HOUR_OF_DAY, hour);
        }
        if (minute != 0) {
            cal.add(Calendar.MINUTE, minute);
        }
        if (second != 0) {
            cal.add(Calendar.SECOND, second);
        }
        return cal.getTime();
    }

    /**
     * 获得当前的年份（年）
     *
     * @return 年份
     */
    public static int getCurrentYear() {
        return getYear(null);
    }

    /**
     * 获得当前的月份（月）
     *
     * @return 月份
     */
    public static int getCurrentMonth() {
        return getMonth(null);
    }

    /**
     * 获得当前的日期（日）
     *
     * @return 日期
     */
    public static int getCurrentDay() {
        return getDay(null);
    }

    /**
     * 获得当前的时间（时）
     *
     * @return 小时
     */
    public static int getCurrentHour() {
        return getHour(null);
    }

    /**
     * 获得当前的分钟（分）
     *
     * @return 分钟
     */
    public static int getCurrentMinute() {
        return getMinute(null);
    }

    /**
     * 获得当前的时间秒（秒）
     *
     * @return 秒
     */
    public static int getCurrentSecond() {
        return getSecond(null);
    }

    /**
     * 获得指定时间的年份
     *
     * @param date 日期date
     * @return 年份
     */
    public static int getYear(Date date) {
        if (date == null) {
            date = new Date();
        }
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        return cal.get(Calendar.YEAR);
    }

    /**
     * 获得指定时间的月份
     *
     * @param date 日期date
     * @return 月份
     */
    public static int getMonth(Date date) {
        if (date == null) {
            date = new Date();
        }
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        return cal.get(Calendar.MONTH) + 1;
    }

    /**
     * 获得指定时间的日
     *
     * @param date 日期date
     * @return 日
     */
    public static int getDay(Date date) {
        if (date == null) {
            date = new Date();
        }
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        return cal.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获得指定时间的小时
     *
     * @param date 日期date
     * @return 小时
     */
    public static int getHour(Date date) {
        if (date == null) {
            date = new Date();
        }
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        return cal.get(Calendar.HOUR_OF_DAY);
    }

    /**
     * 获得指定时间的分钟
     *
     * @param date 日期date
     * @return 分钟
     */
    public static int getMinute(Date date) {
        if (date == null) {
            date = new Date();
        }
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        return cal.get(Calendar.MINUTE);
    }

    /**
     * 获得指定时间的秒
     *
     * @param date 日期date
     * @return 秒
     */
    public static int getSecond(Date date) {
        if (date == null) {
            date = new Date();
        }
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        return cal.get(Calendar.SECOND);
    }

    /**
     * 比较两个时间的差值，相差天数
     *
     * @param d1 日期1
     * @param d2 日期2
     * @return 差值
     */
    public static long getDaysOfDate(@NotNull Date d1, @NotNull Date d2) {
        return (long) Math.floor((double) getMillisecondOfDate(d1, d2) / 1000 / 3600 / 24);
    }

    /**
     * 比较两个时间的差值，相差小时
     *
     * @param d1 日期1
     * @param d2 日期2
     * @return 差值
     */
    public static long getHoursOfDate(Date d1, Date d2) {
        return (long) Math.floor((double) getMillisecondOfDate(d1, d2) / 1000 / 3600);
    }

    /**
     * 比较两个时间的差值，相差分数
     *
     * @param d1 日期1
     * @param d2 日期2
     * @return 差值
     */
    public static long getMinutesOfDate(Date d1, Date d2) {
        return (long) Math.floor((double) getMillisecondOfDate(d1, d2) / 1000 / 60);
    }

    /**
     * 比较两个时间的差值，相差秒
     *
     * @param d1 日期1
     * @param d2 日期2
     * @return 差值
     */
    public static long getSecondsOfDate(Date d1, Date d2) {
        return (long) Math.floor((double) getMillisecondOfDate(d1, d2) / 1000);
    }

    /**
     * 比较两个时间的差值，相差毫秒
     *
     * @param d1 日期1
     * @param d2 日期2
     * @return 差值
     */
    public static long getMillisecondOfDate(@NotNull Date d1, @NotNull Date d2) {
        return d1.getTime() - d2.getTime();
    }

    /**
     * 取得当前月的最大天数
     *
     * @return 天数
     */
    public static int getDaysOfMonth() {
        return getDaysOfMonth(getCurrentYear(), getCurrentMonth());
    }

    /**
     * 取得一个月的最大天数
     *
     * @param year  年份
     * @param month 月份
     * @return 天数
     */
    public static int getDaysOfMonth(int year, int month) {
        return (int) ((toLongTime(month == 12 ? (year + 1) : year,
                month == 12 ? 1 : (month + 1), 1) -
                toLongTime(year, month, 1)) / (24 * 60 * 60 * 1000));
    }


    /**
     * 取得下一个月的最大天数
     *
     * @param year  年份
     * @param month 月份
     * @return 天数
     */
    public static int getDaysOfNextMonth(int year, int month) {
        year = month == 12 ? year + 1 : year;
        month = month == 12 ? 1 : month + 1;
        return getDaysOfMonth(year, month);
    }

    /**
     * 取得上个月的最大天数
     *
     * @param year  年份
     * @param month 月份
     * @return 天数
     */
    public static int getDaysOfPreMonth(int year, int month) {
        year = month == 1 ? year - 1 : year;
        month = month == 1 ? 12 : month - 1;
        return getDaysOfMonth(year, month);
    }

    /**
     * 从给定的 year,month,day 得到时间的long值表示
     * milliseconds after January 1, 1970 00:00:00 GMT).
     *
     * @param year  年
     * @param month 月
     * @param day   日
     * @return 给定的 year,month,day 得到时间的long值表示
     */
    public static long toLongTime(int year, int month, int day) {
        return toDate(year, month, day).getTime();
    }

    /**
     * 从年月日得到一个Date对象
     *
     * @param year  年
     * @param month 月
     * @param day   日
     * @return 得到的Date对象
     */
    public static Date toDate(int year, int month, int day) {
        Calendar cld = new GregorianCalendar();
        cld.clear();
        cld.set(Calendar.YEAR, year);
        cld.set(Calendar.MONTH, month - 1);
        cld.set(Calendar.DAY_OF_MONTH, day);
        return cld.getTime();
    }

    /**
     * 将yyyy-MM-dd时间字符串转换为时间戳字符串
     *
     * @param dateTime 具体时间，跟时间格式对应
     * @return 时间戳
     * @throws ParseException 日期转换异常
     */
    public static String dateToStamp(String dateTime) throws ParseException {
        if (StringUtils.isBlank(dateTime)) {
            return null;
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = simpleDateFormat.parse(dateTime);
        return String.valueOf(date.getTime());
    }

    /**
     * 将yyyy-MM-dd HH:mm:ss时间字符串转换为时间戳字符串
     *
     * @param dateTime 具体时间，跟时间格式对应
     * @return 时间戳
     * @throws ParseException 日期转换异常
     */
    public static String dateTimeToStamp(String dateTime) throws ParseException {
        if (StringUtils.isBlank(dateTime)) {
            return null;
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = simpleDateFormat.parse(dateTime);
        return String.valueOf(date.getTime());
    }

    /**
     * 将时间转换为时间戳字符串
     *
     * @param date 具体时间
     * @return 时间戳
     * @throws ParseException 日期转换异常
     */
    public static String dateToStampStr(Date date) throws ParseException {
        if (ObjectUtils.isEmpty(date)) {
            return null;
        }
        return String.valueOf(date.getTime());
    }

    /**
     * 将时间转换为时间戳long
     *
     * @param date 具体时间
     * @return 时间戳
     */
    public static Long dateToStampLong(Date date) {
        if (ObjectUtils.isEmpty(date)) {
            return null;
        }
        return date.getTime();
    }

    /**
     * 将时间戳字符串转换为yyyy-MM-dd时间字符串
     *
     * @param timestamp 时间戳字符串
     * @return 时间字符串
     */
    public static String stampToDateStr(String timestamp) {
        if (StringUtils.isBlank(timestamp)) {
            return null;
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        long lt = new Long(timestamp);
        return simpleDateFormat.format(new Date(lt));
    }

    /**
     * 将时间戳转换为yyyy-MM-dd HH:mm:ss时间字符串
     *
     * @param timestamp 时间戳字符串
     * @return 时间字符串
     */
    public static String stampToDateTimeStr(String timestamp) {
        if (StringUtils.isBlank(timestamp)) {
            return null;
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long lt = new Long(timestamp);
        return simpleDateFormat.format(new Date(lt));
    }

    /**
     * 将时间戳字符串转换为时间
     *
     * @param timestamp 时间戳字符串
     * @return 时间字符串
     */
    public static Date stampToDateTime(String timestamp) {
        if (StringUtils.isBlank(timestamp)) {
            return null;
        }
        return new Date(new Long(timestamp));
    }

    /**
     * 将时间戳Long转换为时间
     *
     * @param timestamp 时间戳字符串
     * @return 时间字符串
     */
    public static Date stampToDateTime(Long timestamp) {
        if (ObjectUtils.isEmpty(timestamp)) {
            return null;
        }
        return new Date(timestamp);
    }

    /**
     * 将时间戳Long转换为yyyy-MM-dd HH:mm:ss时间字符串
     *
     * @param timestamp 时间戳
     * @return 时间字符串
     */
    public static String stampToDateTimeStr(Long timestamp) {
        if (ObjectUtils.isEmpty(timestamp)) {
            return null;
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return simpleDateFormat.format(new Date(timestamp));
    }

    /**
     * 将时间戳Long转换为yyyy-MM-dd时间字符串
     *
     * @param timestamp 时间戳
     * @return 时间字符串
     */
    public static String stampToDateStr(Long timestamp) {
        if (ObjectUtils.isEmpty(timestamp)) {
            return null;
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return simpleDateFormat.format(new Date(timestamp));
    }

    public static void main(String args[]) {
        //DateTimeUtil du =new DateTimeUtil();
        //log.info(du.getCurrentDateString());
        //log.info(du.getCurrentDate());
    }
}
